package org.btik.light.mobile.ui.devs.espnow.wings;

import android.content.Context;
import android.os.Build;
import android.os.Bundle;
import android.text.Editable;
import android.text.method.ScrollingMovementMethod;
import android.view.View;
import android.widget.*;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import org.btik.context.SimpleContext;
import org.btik.light.mobile.R;
import org.btik.light.mobile.ui.factory.SerialControllerPanel;
import org.btik.light.mobile.ui.serial.controller.console.ConsoleText;
import org.btik.light.mobile.ui.serial.controller.console.SerialConsoleThread;
import org.btik.light.mobile.ui.view.LRSteeringControlView;
import org.btik.light.mobile.ui.view.WingAngleView;
import org.btik.light.mobile.ui.view.YAxisSpeedJoystickView;
import org.btik.light.tool.ByteUtil;

import java.io.IOException;

import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
import static android.view.WindowInsets.Type.statusBars;
import static org.btik.light.mobile.platform.conf.ContextGlobalNames.SELECTED_PORT_INFO;
import static org.btik.light.mobile.ui.devs.espnow.wings.EspnowWingsHandlers.*;

/**
 * @author lustre
 * @since 2023/4/7 17:56
 */
public class EspnowWingsActivity extends SerialControllerPanel {

    private EditText mac;

    private EditText console;

    private ImageButton setMacButton;
    private ImageButton cancelButton;

    private String currentMac = "";

    private SerialConsoleThread serialConsoleThread;
    private ConsoleText consoleText;



    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.espnow_wings);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            getWindow().getDecorView().getWindowInsetsController().hide(statusBars());
        } else {
            getWindow().setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN);
        }

        usbSerialPort = SimpleContext.remove(SELECTED_PORT_INFO);

        String deviceName = usbSerialPort.getDevice().getDeviceName();
        TextView checkedPort = findViewById(R.id.checked_port);
        checkedPort.setText(deviceName);

        // 绑定控制台
        serialConsoleThread = SimpleContext.get(SerialConsoleThread.SERIAL_CONSOLE_THREAD);
        console = findViewById(R.id.console);
        console.setMovementMethod(ScrollingMovementMethod.getInstance());
        serialConsoleThread.attachUsb(usbSerialPort, this::updateConsole);
        bindAction();
        consoleText = new ConsoleText(30, 45);
        console.setText(consoleText);
    }

    private void bindAction() {
        setMacButton = findViewById(R.id.set_mac);
        cancelButton = findViewById(R.id.cancel);
        mac = findViewById(R.id.mac);

        // 滑翔姿态
        WingAngleView leftWing = findViewById(R.id.left_steering_wheel);
        WingAngleView rightWing = findViewById(R.id.right_steering_wheel);

        leftWing.setAngleIntChangeListener(this::leftWingChange);
        rightWing.setAngleIntChangeListener(this::rightWingChange);

        YAxisSpeedJoystickView upDownControl = findViewById(R.id.up_down_control);
        upDownControl.setOnValueChangeListener(this::upDownChange);
        upDownControl.setOnValueResetListener(this::stop);
        LRSteeringControlView lrControl = findViewById(R.id.lr_control);
        lrControl.setOnValueChangeListener(this::lrChange);

    }

    private void updateConsole(final byte[] line, int len) {
        consoleText.print(line, len);
        String msg = consoleText.toString();
        int length = consoleText.length();
        runOnUiThread(() -> {
            console.setText(msg);
            console.refreshDrawableState();
            console.setSelection(length, length);
        });

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (serialConsoleThread != null) {
            serialConsoleThread.detachUsb();
        }

    }

    private void leftWingChange(int angle) {
        //传输的字节本无符号 对端接收一个字节 即可表示 0 ~ 180角度
        byte angleUint8 = (byte) angle;
        SET_LEFT_POSE[3] = angleUint8;
        sendCmd(SET_LEFT_POSE);
    }

    private void rightWingChange(int angle) {
        byte angleUint8 = (byte) angle;
        SET_RIGHT_POSE[3] = angleUint8;
        sendCmd(SET_RIGHT_POSE);
    }

    private void upDownChange(int value) {
        SET_UP_DOWN_VALUE[3] =  (byte) value;
        sendCmd(SET_UP_DOWN_VALUE);
    }

    private void stop(){
        sendCmd(HOLD_ON);
    }

    private void lrChange(int value) {
        SET_RIGHT_LEFT_VALUE[3] =  (byte) value;
        sendCmd(SET_RIGHT_LEFT_VALUE);
    }

    private void enableMac() {
        setMacButton.setBackground(ContextCompat.getDrawable(this, R.drawable.confirm));
        mac.setEnabled(true);
        cancelButton.setVisibility(View.VISIBLE);
    }

    private void disableMac() {
        setMacButton.setBackground(ContextCompat.getDrawable(this, R.drawable.edit));
        mac.setEnabled(false);
        cancelButton.setVisibility(View.GONE);
    }

    public void onCancel(View view) {
        disableMac();
        mac.setText(currentMac);
    }

    public void setMac(View view) {
        final byte[] cmd = SET_MAC;
        Context context = view.getContext();
        if (!mac.isEnabled()) {
            enableMac();
            return;
        }
        Editable text = mac.getText();
        String hexString = text.toString();
        if (hexString.equalsIgnoreCase(currentMac)) {
            disableMac();
            return;
        }
        if (hexString.length() < 12) {
            Toast.makeText(context, R.string.mac_hex_validate, Toast.LENGTH_SHORT).show();
            return;
        }
        try {
            byte[] macAddress = ByteUtil.hexStrToByteArray(hexString);
            System.arraycopy(macAddress, 0, cmd, 2, 6);
        } catch (Exception e) {
            e.printStackTrace();
            Toast.makeText(context, R.string.mac_hex_validate, Toast.LENGTH_SHORT).show();
            return;
        }
        sendCmd(cmd);
        mac.setEnabled(false);
        disableMac();
        currentMac = hexString;
    }

    private void sendCmd(byte[] cmd) {
        try {
            usbSerialPort.write(cmd, 0);
        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(this, R.string.com_send_failed, Toast.LENGTH_SHORT).show();
        }
    }
}
